#include "./conn.h"
#include "../conn/proto.h"
#include "../driver/cmd_uart.h"
#include "../conn/message.h"
#include "../task/mdb_task.h"
#include "../driver/log_uart.h"

namespace service {
using namespace utils;
using namespace conn;
using namespace driver;
using namespace task;

constexpr uint32_t CONN_RECV_BUF_SIZE = 256;
static uint8_t conn_recv_buf[CONN_RECV_BUF_SIZE];
static uint32_t conn_recv_index = 0;
static ByteView conn_recv_slice;
constexpr uint32_t CONN_BYTE_TIMEOUT = 10;

static bool take(uint8_t& v) {
    if (conn_recv_slice.len <= 0) {
        if (osOK != cmdUart.poll(conn_recv_slice, CONN_BYTE_TIMEOUT)) {
            return false;
        }
    }
    v = conn_recv_slice.buf[0];
    conn_recv_slice.buf += 1;
    conn_recv_slice.len -= 1;
    return true;
}

static bool take(uint8_t *buf, uint8_t len) {
    uint8_t index = 0;
    for (; index < len; ) {
        if (conn_recv_slice.len <= 0) {
            if (osOK != cmdUart.poll(conn_recv_slice, CONN_BYTE_TIMEOUT)) {
                return false;
            }
        }
        uint8_t n = len - index;
        if (n > conn_recv_slice.len) {
            n = conn_recv_slice.len;
        }

        memcpy(buf + index, conn_recv_slice.buf, n);
        index += n;
        conn_recv_slice.buf += n;
        conn_recv_slice.len -= n;
    }
    return true;
}


void conn_loop() {
    
    for (;;) {

        if (conn_recv_slice.len <= 0) {
            cmdUart.poll(conn_recv_slice);
        }
        logUart.printf("start recv\r\n");    
        uint8_t head = 0;
        if (!take(head)) {
            logUart.printf("recv err1\r\n");
            continue;
        }

        if (head != proto::HEAD) {
            logUart.printf("recv err2\r\n");
            continue;;
        }

        uint8_t len = 0;
        if (!take(len)) {
            logUart.printf("recv err3\r\n");
            continue;
        }

        if (len < 5) {
            logUart.printf("recv err4\r\n");
            continue;
        }
        len -= 2;
        if ((conn_recv_index + len) >= CONN_RECV_BUF_SIZE) {
            conn_recv_index = 0;
        }
        uint8_t *buf = conn_recv_buf + conn_recv_index;

        if (!take(buf, len)) {
            logUart.printf("recv err5\r\n");
            continue;
        }
        uint8_t s = utils::alg::xor_sum(buf + 1, len - 3);
        if (s != buf[len - 2]) {
            logUart.printf("recv err6\r\n");
            continue;
        }
        if (proto::END != buf[len - 1]) {
            logUart.printf("recv err7\r\n");
            continue;
        }
        logUart.printf("recv succ\r\n");
        conn_recv_index += len;
        Message msg(buf, len);
        mdbTask.post(msg);
    }
}

}




